package com.hqq.persistence_tier.dao;

import org.h2.jdbcx.JdbcDataSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

/**
 * 数据访问对象[DAO]是一个提供了抽象接口的对象 其中提供了一系列持久层机制
 * 通过把应用层的调用映射到持久层,DAO提供了很多数据操作,无需暴露数据库内部细节
 * Created by heqianqian on 2017/8/9.
 */
public class App {

    private static final String DB_URL = "jdbc:h2:~/dao";//dao是数据库名称
    private static Logger LOGGER = LoggerFactory.getLogger(App.class);


    public static void main(String[] args) throws Exception {
        //测试InMemoryCustomerDao
        final CustomerDao inMemoryDao = new InMemoryCustomerDao();
        performOperationUsing(inMemoryDao);

        //测试DBCustomerDao
        final DataSource dataSource = createDataSource();
        createSchema(dataSource);//创建表
        final CustomerDao dbDao = new DBCustomerDao(dataSource);
        performOperationUsing(dbDao);
        deleteSchema(dataSource);//删除表
    }

    private static void deleteSchema(DataSource dataSource) throws Exception {
        try (Connection connection = dataSource.getConnection();
             PreparedStatement psmt = connection.prepareStatement(CustomerSchemaSql.DELETE_SCHEMA_SQL);) {
            psmt.execute();
        } catch (Exception e) {
            throw new Exception(e);
        }
    }

    private static void createSchema(DataSource dataSource) throws Exception {
        try (Connection connection = dataSource.getConnection();
             PreparedStatement psmt = connection.prepareStatement(CustomerSchemaSql.CREATE_SCHEMA_SQL);) {
            psmt.execute();
        } catch (Exception e) {
            throw new Exception(e);
        }
    }

    private static DataSource createDataSource() {
        JdbcDataSource dataSource = new JdbcDataSource();
        dataSource.setURL(DB_URL);
        return dataSource;
    }

    private static void performOperationUsing(final CustomerDao customerDao) throws Exception {
        addCustomers(customerDao);//添加数据
        //测试getAll
        printCustomers(customerDao);
        //测试getById(int)
        LOGGER.info("customerDao.getCustomerById(2): " + customerDao.getById(2));
        //测试add
        LOGGER.info("customerDao.add:");
        final Customer customer = new Customer(4, "Dan", "Danson");
        customerDao.add(customer);
        printCustomers(customerDao);
        //测试update
        LOGGER.info("customerDao.update:");
        customer.setFirstName("Daniel");
        customer.setLastName("Danielson");
        customerDao.update(customer);
        printCustomers(customerDao);
        //测试delete
        LOGGER.info("customerDao.delete:");
        customerDao.delete(customer);
        printCustomers(customerDao);
    }

    private static void printCustomers(CustomerDao customerDao) {
        LOGGER.info("customerDao.getAllCustomers(): ");
        try (Stream<Customer> customerStream = customerDao.getAll()) {
            customerStream.forEach(customer -> LOGGER.info(customer.toString()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void addCustomers(CustomerDao customerDao) throws Exception {
        for (Customer customer : generateSampleCustomers()) {
            customerDao.add(customer);
        }
    }

    /**
     * 产生Customer的数据
     *
     * @return Customer对象集合
     */
    private static List<Customer> generateSampleCustomers() {
        final Customer customer1 = new Customer(1, "Adam", "Adamson");
        final Customer customer2 = new Customer(2, "Bob", "Bobson");
        final Customer customer3 = new Customer(3, "Carl", "Carlson");
        final List<Customer> customers = new ArrayList<>();
        customers.add(customer1);
        customers.add(customer2);
        customers.add(customer3);
        return customers;
    }


}
